#include "libcard.h"

#define MAX_BUF_SIZE		255
//#define DEBUG
//#define USER_CARD

//数据起始，终止标志
#define STX 0x02
#define ETX 0x03

//数据来源方向
#define SEND 0x01
#define RECV 0x02

//卡的状态
enum card_status{
	CARD_EXIST = 0x30,
	CARD_NO_EXIST  = 0x31,
	SYSTEM_CARD = 0x30,
	NOT_SYSTEM_CARD = 0x31
};

typedef struct {
	rf_card* card;
	int uart_fd;
	int card_status;// 0:卡机内有卡 1:卡机内无卡
	int system_card_type;//0:系统卡  1:非系统卡
	int ICtype;//0x01:用户卡  0x00:返回状态字为 0x4E 时为 0x00
	pthread_mutex_t* card_mutex;
	pthread_t pthread_id;
	int grey_lock_state;//灰锁状态
	int offline_tran_times;//脱机交易次数
	int online_tran_times;//联机交易次数

	bool read_card_flag;//false:退出读卡  true:开始读卡
	bool  seek_card_flag;//寻卡标志 true开心寻卡  false不允许寻卡
}card_t;

card_t g_card;


//获取有效的校验值
int get_valid_bcc(const uint8 *buf, int len, int direction)
{
	int index = 0;
	uint8 bcc = 0;
	int data_len = 0;
	int i = 0;

	if((buf == NULL) || (len <= 0) || ((direction != SEND) && (direction != RECV))){
		printf("##libcard## get valid bcc para err!!!\n");
		return -1;
	}

#if 0
	for(index=0; index<len; index++){
		if(buf[index] == STX)
			break;
	}

	//防止访问越界
	if(direction == SEND){
		if(index > (len-6))
			return -1;
	}
	else if(direction == RECV){
		if(index > (len-7))
			return -1;
	}
	else{
		printf("##libcard## get valid bcc para err2!!!\n");
		return -1;
	}
#endif

	if(buf[index] != STX && buf[len-2] != ETX){
		printf("##libcard## get valid bcc para err2!!!\n");
		return -1;
	}

	for(i=0; i<(len-1); i++)
		bcc ^= buf[i];

	//    index++;
	//    data_len = (buf[index]<<8) | buf[index+1];
	//
	//    if(direction == SEND){
	//    	/*
	//        data_len -= 2;
	//        bcc = buf[index] ^ buf[index+1] ^ buf[index+2] ^ buf[index+3];
	//        index += 4;
	//        for(i=0; i<data_len; i++){
	//            bcc ^= buf[index+i];
	//        }
	//        */
	//    	for(i=0; i<(len-1); i++)
	//    		bcc ^= buf[i];
	//    }
	//
	//    if(direction == RECV){
	//    	/*
	//        data_len -= 3;
	//        bcc = buf[index] ^ buf[index+1] ^ buf[index+2] ^ buf[index+3] ^ buf[index+4];
	//        index +=5;
	//        for(i=0; i<data_len;i++){
	//            bcc ^= buf[index+i];
	//        }
	//        */
	//        for(i=0; i<(len-1); i++)
	//            		bcc ^= buf[i];
	//    }

	return bcc;
}

//获取接收的校验值
int get_recv_bcc(uint8 *buf, int len)
{

	int index = 0;
	uint8 bcc = 0;
	int data_len = 0;

	if((buf == NULL) || len <= 0)
		return -1;
#if 0
	for(index=0; index<len; index++){
		if(buf[index] == STX)
			break;
	}
	if(index >= len)
		return -1;
#endif

	if(buf[index] != STX && buf[len-2] != ETX){
		printf("##libcard## get recv bcc para err!!!\n");
		return -1;
	}
	//
	//    data_len = (buf[index+1]<8) | buf[index+2];
	//    index +=5;
	//    index += data_len -3;
	//    index += 2;
	//    bcc = buf[index];
	bcc = buf[len-1];

	return bcc;
}

int uart_send(const int fd, const uint8 *buf, int len)
{
	int sended = 0;
	int i;

	if((fd < 0) || (buf == NULL) || (len <= 0))
		return -1;

	sended = write(fd, buf, len);
	if( sended <= 0) {
		printf("##libcard##--Port send [%d] error.\n ", sended);
	}

#ifdef DEBUG
	printf("##libcard## card send data[%03d] -->", sended);
	for(i=0; i < sended; i++) {
		printf("%02x ", buf[i]);
	}
	printf("\n");
	printf("##libcard## card send data bbc1=%02x, bcc2=%02x\n",get_valid_bcc(buf,len,SEND), buf[len-1]);
#endif

	return sended;
}



int is_recv_complete(const uint8* buf, int len)
{
	int index = 0;
	int data_len = 0;

	if(buf == NULL)
		return -1;


	if(buf[index] != STX)
		return -1;



	if(buf[len-2] == ETX){
#ifdef DEBUG
		printf("##libcard## data recv complete\n");
#endif
		return 0;
	}
	else{
#ifdef DEBUG
		printf("##libcard## data recv no complete\n");
#endif
		return 1;
	}
}

int listen_recv(const int fd, uint8 *buf, int rlen, int timeout)
{
	int len = 0, total_len = 0;
	int count =0;
	int ret;
	int i = 0;
	fd_set fdset;
	int check_ret = -1;
	uint8 *p = NULL;

	struct timeval tm;

	if (fd < 0 || rlen<0 || rlen> MAX_BUF_SIZE)
	{
		printf(" ##libcard## listen_recv param err !\n");
		return -1;
	}

	p = buf;
	tm.tv_sec = timeout/1000;
	tm.tv_usec = (timeout%1000)*1000;

	while(count<3)
	{
		FD_ZERO(&fdset);
		FD_SET(fd, &fdset);
		ret = select(fd + 1, &fdset, NULL, NULL, &tm);
		if(ret < 0){
			perror("##libcard## select failued !\n ");
			break;
		}
		else if(ret == 0){
			++count; //timeout
		}
		else if(FD_ISSET(fd, &fdset)){
			rlen = rlen-len;
			len = read(fd, buf, rlen);
#ifdef DEBUG
			printf("-----------recv");
			for(i=0; i<len; i++)
				printf("%02x ",buf[i]);
			printf("\n");
#endif
			total_len += len;
			buf = p;

			check_ret = is_recv_complete(buf,total_len);
			if(check_ret == 0)
				break;
			else if(check_ret == 1){
				buf = buf+total_len;
				continue;
			}
			else{
				memset(buf,0,rlen);
				len = 0;
				printf("##libcard## Recv Trash Data\n");
				break;
			}
		}
	}
	if(count >= 3){
		printf("##libcard##read timeout!\n");
		return -1;
	}

	int bcc1 = 0,bcc2 = 0;
	bcc1 = get_valid_bcc(buf,total_len,RECV);
	bcc2 = get_recv_bcc(buf,total_len);

#ifdef DEBUG
	printf("##libcard## card recv data[%d]-->",total_len);
	for(i=0; i<total_len; i++)
		printf("%02x ",buf[i]);
	printf("\n");
	printf("##libcard## card recv data bbc1=%02x, bbc2=%02x\n",bcc1,bcc2);
#endif

	if((bcc1 != bcc2) || (bcc1 == -1) || (bcc2 == -1))
		return -1;

	return total_len;
}


int port_open(card_uart_para *port)
{
	int fd = 0;
	card_uart_para *com = port;

	if(NULL == com)	return -1;

	//打开串口设备
	fd = open(com->name, O_RDWR|O_NOCTTY|O_NONBLOCK);
	if(fd < 0) {
		printf("##libcard##--Open PORT: [%s] failure.\n", com->name);
	}
	return fd;
}

int speed_to_flag(int speed)
{
	uint32 i;
	int cnt = 0;

	for (i = 0; i < sizeof(speed_arr)/sizeof(int); i++) {
		cnt = (speed - speed_arr[i]);
		if ( cnt == 0)
			return baudflag_arr[i];
	}

	printf("##libcard##--Unsupported baudrate, use 9600 instead!\n");
	return B9600;
}

int port_setup(int fd, card_uart_para *port)
{
	card_uart_para *com = port;
	struct termios old_tio, new_tio;
	int baud_rate = 0;

	if(fd < 0)		return -1;
	if(NULL == com)		return -1;

	tcgetattr(fd, &old_tio);
	bzero(&new_tio, sizeof(struct termios));
	new_tio.c_cflag |= (CLOCAL | CREAD);

	//设置波特率
	baud_rate = speed_to_flag(com->baud);
	new_tio.c_cflag |= baud_rate;
	//设置停止位
	switch(com->stop_bits) {
	case 1:
		new_tio.c_cflag &= ~CSTOPB;
		break;
	case 2:
		new_tio.c_cflag |= CSTOPB;
		break;
	default:
		printf("##libcard##--PORT stop bits set error. use default.\n");
		new_tio.c_cflag &= ~CSTOPB;
		break;
	}

	//设置奇偶校验
	switch(com->parity) {
	case 0://无校验
		new_tio.c_cflag &= ~PARENB;
		break;
	case 1://奇校验
		new_tio.c_cflag |= (PARENB | PARODD);
		break;
	case 2://偶校验
		new_tio.c_cflag |= PARENB;
		new_tio.c_cflag &= ~PARODD;
		break;
	case 3://MARK校验
		new_tio.c_cflag |= (PARENB | PARODD);
		new_tio.c_cflag |= CMSPAR;
		break;
	case 4://SPACE校验
		new_tio.c_cflag |= PARENB;
		new_tio.c_cflag &= ~PARODD;
		new_tio.c_cflag |= CMSPAR;
		break;
	default:
		printf("##libcard##--PORT parity set error. use default.\n");
		new_tio.c_cflag &= ~PARENB;
		break;
	}
	new_tio.c_cflag &= ~CSIZE;
	switch(com->data_bits) {
	case 5:
		new_tio.c_cflag |= CS5;
		break;
	case 6:
		new_tio.c_cflag |= CS6;
		break;
	case 7:
		new_tio.c_cflag |= CS7;
		break;
	case 8:
		new_tio.c_cflag |= CS8;
		break;
	default:
		printf("##libcard##--PORT data bits set error. use default.\n");
		new_tio.c_cflag |= CS8;
		break;
	}

	//设置无硬件流控
	new_tio.c_cflag &= ~CRTSCTS;
	new_tio.c_lflag = 0;
	new_tio.c_oflag = 0;
	new_tio.c_cc[VMIN] = 1;
	new_tio.c_cc[VTIME] = 0;
	new_tio.c_iflag &= ~(IXON | IXOFF | IXANY);

	cfsetispeed(&new_tio, baud_rate);
	cfsetospeed(&new_tio, baud_rate);
	tcsetattr(fd, TCSANOW, &new_tio);
	tcflush(fd, TCIFLUSH);

	return 0;
}

void setTimer(unsigned int seconds, unsigned int mseconds)
{
	struct timeval temp;

	temp.tv_sec = seconds + (mseconds/1000);
	temp.tv_usec = (mseconds%1000)*1000;

	select(0, NULL, NULL, NULL, &temp);

	return ;
}

//检查版本,同时检测读卡器的通信是否断开
void* protocol_seek_card(void* arg)
{
	uint8 cmd[7] = {0x02,0x00,0x02,0x51,0x37,0x03};
	uint8 data[MAX_BUF_SIZE] = {0};
	static int err_count = 0;
	int len = 0;

	cmd[6] = get_valid_bcc(cmd,sizeof(cmd)/sizeof(uint8),SEND);

	g_card.seek_card_flag = true;

	while(1){
		printf("##libcard MT##card status:%02x   card type:%02x  errcode:%d\n",g_card.card_status, g_card.system_card_type,g_card.card->errcode);

		if(g_card.seek_card_flag == false)
		{
			setTimer(1,0);
			continue;
		}
		memset(data,0,sizeof(data));
		setTimer(2,0);

		pthread_mutex_lock(g_card.card_mutex);
		if((uart_send(g_card.uart_fd, cmd, sizeof(cmd))) < 0){
			printf("##libcard## seek card send error\n");
			g_card.card->errcode = 1;//通信异常
			g_card.card_status = CARD_NO_EXIST;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
		if(len <= 0){
			printf("##libcard## seek card listen_recv timeout or error!\n");
			if(err_count >= 3){
				g_card.card->errcode = 1;//通信异常
				g_card.card_status = CARD_NO_EXIST;
			}
			pthread_mutex_unlock(g_card.card_mutex);

			err_count++;
			continue;
		}

		if((data[0] != 0x02) || (data[3] != 0x51) || (data[4] != 0x37) || (data[5] != 0x59)){
			if(err_count >= 3){
				printf("##libcard## seek card  , card reponse error!\n");
				g_card.card->errcode = 1;//连续3次检查版本失败，通信异常
				g_card.card_status = CARD_NO_EXIST;
			}

			err_count++;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}
		g_card.card->errcode = 0;//通信正常
		err_count = 0;
		if(data[6] == CARD_EXIST)
			g_card.card_status = CARD_EXIST;
		else if(data[6] == CARD_NO_EXIST)
			g_card.card_status = CARD_NO_EXIST;

		if(data[7] == SYSTEM_CARD)
			g_card.system_card_type = SYSTEM_CARD;
		else if(data[7] == NOT_SYSTEM_CARD)
			g_card.system_card_type = NOT_SYSTEM_CARD;

		//		printf("##libcard## seek card reponse successful, card status:%02x   card type:%02x  errcode:%d\n",g_card.card_status, g_card.system_card_type,g_card.card->errcode);
		pthread_mutex_unlock(g_card.card_mutex);
	}

	return NULL;
}

//初始化函数，pcard指向一个rf_card结构， plock指向pthread_mutex_t互斥量, 指向sem_t信号量,在检测到刷卡时置位。//返回0成功，1 失败
int protocol_card_init(void * pcard, void *plock, void *psem) 
{
	int fd = 0;

	if((pcard == NULL) || (plock == NULL) || (psem == NULL)){
		printf("##libcard## init card faile, due to para is NULL!!!\n");
		return 1;
	}


	g_card.card = (rf_card*)pcard;
	g_card.card_mutex = (pthread_mutex_t*)plock;

	if((fd = port_open(&(g_card.card->com))) == -1 )
	{
		printf("##libcard error## open device fail\n");
		return 1;
	}

	g_card.uart_fd = fd;
	g_card.card->com.baud = 115200;
	port_setup(g_card.uart_fd,&(g_card.card->com));
	pthread_create(&g_card.pthread_id,NULL,protocol_seek_card,NULL);

	printf("##libcard Init##uart name:%s uart baud:%d uart data_bit:%d uart parity:%d uart stop_bits:%d",g_card.card->com.name, g_card.card->com.baud,
			g_card.card->com.data_bits, g_card.card->com.parity, g_card.card->com.stop_bits);

	printf("uart fd is:%d\n",g_card.uart_fd);

	return 0;
}

//关闭函数，释放资源
int protocol_card_close()//返回0成功，1 失败
{

	return 0;
}

//预处理
int before_deal(uint8* pass, int len)
{
	uint8 cmd[17] = {0};
	uint8 data[MAX_BUF_SIZE] = {0};
	time_t timep;
	struct tm *now = NULL;
	int year,mon,day,hour,minute,second;
	int re_len = 0;
	int i = 0;
	int state = 0;

	if((pass == NULL) || (len != 3)){
		printf("##libcard## before deal fail, due to para err!\n");
		return -1;
	}

	time(&timep);
	now = localtime(&timep);
	year = now->tm_year +1900;
	mon = now->tm_mon  + 1;
	day = now->tm_mday;
	hour = now->tm_hour;
	minute = now->tm_min;
	second = now->tm_sec;

	cmd[0] = STX;
	cmd[1] = 0x00;
	cmd[2] = 0x0C;
	cmd[3] = 0x51;
	cmd[4] = 0x36;
	cmd[5] = year>>8;
	cmd[6] = year;
	cmd[7] = mon;
	cmd[8] = day;
	cmd[9] = hour;
	cmd[10] = minute;
	cmd[11] = second;
	cmd[12] = pass[0];
	cmd[13] = pass[1];
	cmd[14] = pass[2];
	cmd[15] = ETX;
	cmd[16] = get_valid_bcc(cmd,sizeof(cmd),SEND);


	pthread_mutex_lock(g_card.card_mutex);
	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard## before deal fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1000);
	if(re_len <= 0){
		printf("##libcard## before deal fail, due to uart listen recv fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	if((data[0] == STX ) && (data[1] == 0x00) && (data[2] == 0x17) && (data[3] == 0x51) && (data[4] == 0x36)){
		state = data[5];
		if(state == 0x59){
			g_card.ICtype = data[6];
			g_card.card->cardtype = data[6];
			g_card.grey_lock_state = data[7];

			for(i=0;i<8;i++)
				g_card.card->cardNUM[i] = data[8+i];

			g_card.card->available_money = (data[16]<<24) | (data[17]<<16) | (data[18]<<8) | data[19];
			g_card.offline_tran_times = data[20]<<8 | data[21];
			g_card.online_tran_times = data[22]<<8 | data[23];
			printf("##libcard## before deal success!!!\n");
		}
		else{
			printf("##libcard## before deal fail, card return state byte:%02x\n",data[5]);
		}
	}
	else{
		printf("##libcard## before deal fail, due to recv data check fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	pthread_mutex_unlock(g_card.card_mutex);

	return state;
}

//补充交易
int supplement_tran(void)
{
	uint8 cmd[7] = {STX,0x00,0x02,0x51,0x35,ETX};
	uint8 data[MAX_BUF_SIZE] = {0};
	int re_len = 0;
	int i = 0;
	int state = 0;

	cmd[6] = get_valid_bcc(cmd,sizeof(cmd),SEND);

	pthread_mutex_lock(g_card.card_mutex);

	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard## supplement tran fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1);
	if(re_len <= 0){
		printf("##libcard## supplement tran fail, due to uart listen recv fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	if((data[0] == STX ) && (data[1] == 0x00) && (data[2] == 0x2D) && (data[3] == 0x51) && (data[4] == 0x35)){
		state = data[5];
		if(state == 0x59){
			for(i=0; i<8; i++)
				g_card.card->cardNUM[i] = data[6+i];
			g_card.card->rand = data[14]<<24 | data[15]<<16 | data[16]<<8 | data[17];
			g_card.card->available_money = data[20]<<24 | data[21]<<16 | data[22]<<8 | data[23];
			printf("##libcard## supplement tran success!\n");
		}
		else
		{
			printf("##libcard## supplement tran fail, card return state byte:%02x\n",data[5]);
		}
	}
	else
	{
		printf("##libcard## supplement tran fail, due to recv data check fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	pthread_mutex_unlock(g_card.card_mutex);

	return state;
}

//弹卡
int sprang_open_card(void)
{
	uint8 cmd[7] = {STX,0x00,0x02,0x32,0x40,ETX};
	uint8 data[MAX_BUF_SIZE] = {0};
	int re_len = 0;
	int state = 0;

	cmd[6] = get_valid_bcc(cmd,sizeof(cmd),SEND);

	pthread_mutex_lock(g_card.card_mutex);

	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard## sprang open card fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1);
	if(re_len <= 0){
		printf("##libcard## sprang open card fail,, due to uart listen recv fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	if((data[0] == STX ) && (data[1] == 0x00) && (data[2] == 0x03) && (data[3] == 0x32) && (data[4] == 0x40)){
		state = data[5];
		if(state != 0x30)
		{
			printf("##libcard## sprang open card fail, card return state byte:%02x\n",data[5]);
		}
	}
	else
	{
		printf("##libcard## sprang open card fail, due to recv data check fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	pthread_mutex_unlock(g_card.card_mutex);

	return state;
}

//验证卡片合法性并读取卡号
int check_card_valid(void)
{
	uint8 cmd[7] = {STX,0x00,0x02,0x51,0x56,ETX};
	uint8 data[MAX_BUF_SIZE] = {0};
	int re_len = 0;
	int i = 0;
	int state = 0;

	cmd[6] = get_valid_bcc(cmd,sizeof(cmd),SEND);

	pthread_mutex_lock(g_card.card_mutex);

	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard## check card valid fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1000);
	if(re_len <= 0){
		printf("##libcard## check card valid fail,, due to uart listen recv fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	if((data[0] == STX ) && (data[3] == 0x51) && (data[4] == 0x56)){
		state = data[5];
		if(state == 0x59){
			g_card.card->cardtype = data[6];
			for(i=0; i<8; i++)
				g_card.card->cardNUM[i] = data[7+i];
		}
		else
		{
			printf("##libcard## check card valid fail, card return state byte:%02x\n",data[5]);
		}
	}
	else
	{
		printf("##libcard## check card valid fail, due to recv data check fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	pthread_mutex_unlock(g_card.card_mutex);

	return state;
}

//关闭射频
int close_card_rf(void)
{
	uint8 cmd[7] = {STX,0x00,0x02,0x34,0x42,ETX};
	uint8 data[MAX_BUF_SIZE] = {0};
	int re_len = 0;
	int state = 0;

	cmd[6] = get_valid_bcc(cmd,sizeof(cmd),SEND);

	pthread_mutex_lock(g_card.card_mutex);

	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard## close card RF fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1);
	if(re_len <= 0){
		printf("##libcard## close card RF fail, due to uart listen recv fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	if((data[0] == STX ) && (data[1] == 0x00) && (data[2] == 0x03) && (data[3] == 0x34) && (data[4] == 0x42)){
		state = data[5];
		if(state != 0x59)
		{
			printf("##libcard##close card RF fail, card return state byte:%02x\n",data[5]);
		}
	}
	else
	{
		printf("##libcard## close card RF fail, due to recv data check fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	pthread_mutex_unlock(g_card.card_mutex);
	return state;
}

//开始加电  控制读卡器对用户卡和充值卡锁卡操作
int begin_lock_card(void)
{
	uint8 cmd[14] = {0};
	uint8 data[MAX_BUF_SIZE] = {0};
	time_t timep;
	struct tm *now = NULL;
	int year,mon,day,hour,minute,second;
	int re_len = 0;
	int state = 0;

	time(&timep);
	now = localtime(&timep);
	year = now->tm_year +1900;
	mon = now->tm_mon  + 1;
	day = now->tm_mday;
	hour = now->tm_hour;
	minute = now->tm_min;
	second = now->tm_sec;

	cmd[0] = STX;
	cmd[1] = 0x00;
	cmd[2] = 0x09;
	cmd[3] = 0x51;
	cmd[4] = 0x30;
	cmd[5] = year>>8;
	cmd[6] = year;
	cmd[7] = mon;
	cmd[8] = day;
	cmd[9] = hour;
	cmd[10] = minute;
	cmd[11] = second;
	cmd[12] = ETX;
	cmd[13] = get_valid_bcc(cmd,sizeof(cmd),SEND);

	pthread_mutex_lock(g_card.card_mutex);

	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard## begin lock card fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1);
	if(re_len <= 0){
		printf("##libcard## begin lock card fail, due to uart listen recv fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	if((data[0] == STX ) && (data[1] == 0x00) && (data[2] == 0x07) && (data[3] == 0x51) && (data[4] == 0x30)){
		state = data[5];
		if(state == 0x59){
			g_card.card->available_money = data[6]<<24 | data[7]<<16 | data[8]<<8 | data[9];
		}
		else
		{
			printf("##libcard## begin lock card fail, card return state byte:%02x\n",data[5]);
		}
	}
	else
	{
		printf("##libcard## begin lock card fail, due to recv data check fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	pthread_mutex_unlock(g_card.card_mutex);

	return state;
}

int end_unlock_card(int money)
{
	uint8 cmd[18] = {0};
	uint8 data[MAX_BUF_SIZE] = {0};
	time_t timep;
	struct tm *now = NULL;
	int year,mon,day,hour,minute,second;
	int re_len = 0;
	int state = 0;

	time(&timep);
	now = localtime(&timep);
	year = now->tm_year +1900;
	mon = now->tm_mon  + 1;
	day = now->tm_mday;
	hour = now->tm_hour;
	minute = now->tm_min;
	second = now->tm_sec;

	cmd[0] = STX;
	cmd[1] = 0x00;
	cmd[2] = 0x0D;
	cmd[3] = 0x51;
	cmd[4] = 0x34;
	cmd[5] = money>>24;
	cmd[6] = money>>16;
	cmd[7] = money>>8;
	cmd[8] = money;
	cmd[9] = year>>8;
	cmd[10] = year;
	cmd[11] = mon;
	cmd[12] = day;
	cmd[13] = hour;
	cmd[14] = minute;
	cmd[15] = second;
	cmd[16] = ETX;
	cmd[17] = get_valid_bcc(cmd,sizeof(cmd),SEND);

	pthread_mutex_lock(g_card.card_mutex);

	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard## end unlock card fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1);
	if(re_len <= 0){
		printf("##libcard## end unlock card fail, due to uart listen recv fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	if((data[0] == STX ) && (data[1] == 0x00) && (data[2] == 0x07) && (data[3] == 0x51) && (data[4] == 0x34)){
		state = data[5];
		if(state == 0x59){
			g_card.card->available_money = data[6]<<24 | data[7]<<16 | data[8]<<8 | data[9];
		}
		else
		{
			printf("##libcard## end unlock card fail, card return state byte:%02x\n",data[5]);
		}
	}
	else
	{
		printf("##libcard## end unlock card fail, due to recv data check fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	pthread_mutex_unlock(g_card.card_mutex);

	return state;
}



////激活卡函数，delaytime 等待时间，cardtype 返回的卡类型，UIDLen返回的卡号长度，cardUID指向一个32字节大小的内存，用于存储返回的卡号。
int protocol_enabled_card(short delaytime, char *cardtype, unsigned char *UIDLen, char * cardUID) //返回0成功，1 失败
{
	uint8 cmd[7] = {0};
	uint8 data[MAX_BUF_SIZE] = {0};
	int re_len = 0;

	cmd[0] = STX;
	cmd[1] = 0x00;
	cmd[2] = 0x02;
	cmd[3] = 0x34;
	cmd[4] = 0x40;
	cmd[5] = 0x03;
	cmd[6] = get_valid_bcc(cmd,sizeof(cmd),SEND);

	pthread_mutex_lock(g_card.card_mutex);

	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard MT## enable card fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	//	setTimer(1,0);
	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1000);
	if(re_len <= 0){
		printf("##libcard MT## enable card fail, due to uart listen recv fail!\n");
		g_card.card->errcode = 1;//通信异常
		g_card.card_status = CARD_NO_EXIST;

		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	if((data[0] == STX ) && (data[3] == 0x34) && (data[4] == 0x40)){
		if(data[5] == 0x59){
			printf("##libcard MT## enable card success!!!\n");
		}
		else
		{
			printf("##libcard MT## enable card fail, card return state byte:%02x\n",data[5]);
			pthread_mutex_unlock(g_card.card_mutex);
			return 1;
		}
	}
	else
	{
		printf("##libcard MT## enable card fail, due to recv data check fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	pthread_mutex_unlock(g_card.card_mutex);

	return 0;
}

int read_card_num(void)
{
	uint8 cmd[14] = {0x02,0x00,0x09,0x34,0x41,0x00,0x05,0x00,0xB0,0x81,0x00,0x08,0x03,0x41};//物理卡号
	//	uint8 cmd[7] = {0x02,0x00,0x02,0x34,0x31,0x03,0x06};//卡的固化序列号
	uint8 data[MAX_BUF_SIZE] = {0};
	int re_len = 0;
	int i = 0;

	//	g_card.card->errcode = 1;//通信异常
	//	g_card.card_status = CARD_NO_EXIST;

	if(g_card.card->errcode != 0){
		printf("##libcard MT ## read card num fail, due to errcode =1\n");
		return 1;
	}

	pthread_mutex_lock(g_card.card_mutex);

	re_len = uart_send(g_card.uart_fd,cmd,sizeof(cmd));
	if(re_len <= 0){
		printf("##libcard MT## read card num fail, due to uart send fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	re_len = listen_recv(g_card.uart_fd,data,sizeof(data),1000);
	if(re_len <= 0){
		printf("##libcard MT## read card num , due to uart listen recv fail!\n");
		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	if((data[0] == STX ) && (data[3] == 0x34) && (data[4] == 0x41)){
		if(data[5] == 0x59){
			printf("--------------------Card Num------------------\n");
			memset(g_card.card->cardNUM,0,sizeof(g_card.card->cardNUM));
			for(i=0; i<8; i++){
				g_card.card->cardNUM[i] = (short)data[8+i];
				printf("%02x",g_card.card->cardNUM[i]);
			}
			printf("\n##libcard MT## read card num  success!!!\n");
		}
		else
		{
			printf("##libcard MT## read card num , card return state byte:%02x\n",data[5]);
			pthread_mutex_unlock(g_card.card_mutex);
			return 1;
		}
	}
	else
	{
		printf("##libcard MT## read card num fail , due to recv data check fail!  status:%02x \n",data[5]);

		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	pthread_mutex_unlock(g_card.card_mutex);
	return 0;
}

void clear_card_info(void)
{    
	memset(&(g_card.card->UIDLen),0,sizeof(unsigned char));
	memset(g_card.card->cardUID,0,sizeof(g_card.card->cardUID));
	memset(g_card.card->cmd1,0,sizeof(g_card.card->cmd1));
	memset(g_card.card->cmd2,0,sizeof(g_card.card->cmd2));
	memset(g_card.card->cmd3,0,sizeof(g_card.card->cmd3));
	memset(g_card.card->cardNUM,0,sizeof(g_card.card->cardNUM));
	memset(&(g_card.card->available_money),0,sizeof(unsigned int));
	memset(&(g_card.card->ver),0,sizeof(char));
	memset(&(g_card.card->tag),0,sizeof(char));
	memset(&(g_card.card->rand),0,sizeof(int));
	memset(&(g_card.card->mac),0,sizeof(int));
}

//读卡查询函数，money 返回卡余额，locknum 返回灰锁次数。
int protocol_read_card(float *money, char *locknum) //返回0成功，1 失败
{
	int i = 0, j = 0;
	int seek_count = 30;
	int re_state = 0;
	uint8 ch = 0;

	clear_card_info();
	g_card.read_card_flag = true;
	g_card.seek_card_flag = true;

	//	g_card.card_status = CARD_EXIST;//debug

	for(i=0; i<seek_count; i++){
		if(g_card.read_card_flag != true){
			printf("##libcard## exit seek card status!\n");
			g_card.seek_card_flag = true;
			return 1;
		}

		if(g_card.card_status == CARD_EXIST)
			break;

		setTimer(1,0);
	}
	if(i >= seek_count){
		printf("##libcard## read card fail, due to card no exist!\n");
		g_card.seek_card_flag = true;
		return 1;
	}

	g_card.seek_card_flag = false;

	for(i=0; i<3; i++){
		if(protocol_enabled_card(0,NULL,NULL,NULL) == 0){
			for(j=0; j<3; j++){
				if(read_card_num() == 0){
					g_card.seek_card_flag = true;
					return 0;
				}
				else
				{
					setTimer(0,500);
				}
			}
		}
		else{
			setTimer(0,500);
			continue;
		}
	}

	if((i >= 3) || (j >= 3)){
		g_card.seek_card_flag = true;
		return 1;
	}


#if 0

	re_state = check_card_valid();
	if(re_state == 0x47 || re_state == 0x4E || re_state == 0x48)
	{
		//		printf("##libcard## check card valid success!\n");
		re_state =  before_deal(g_card.card->pass,sizeof(g_card.card->pass));
		if(re_state == 0x59){
			*money = (float)g_card.card->available_money /100;
			*locknum = g_card.offline_tran_times;
#ifdef USER_CARD
			re_state = begin_lock_card();
			if(re_state != 0x59){
				g_card.seek_card_flag = true;
				return 1;
			}
#endif
		}
		else{
			g_card.seek_card_flag = true;
			return 1;
		}
	}
	else if(re_state == 0x59){
		g_card.seek_card_flag = true;
		return 0;
	}
	else{
		g_card.seek_card_flag = true;
		return 1;
	}

#endif

	g_card.seek_card_flag = true;
	return 0;
}

//写卡数据函数，money消费费用，locknum 灰锁次数。
int protocol_write_card(float money, char locknum)//返回0成功，1 失败
{
	int i = 0;
	int seek_count = 30;
	int re_state = 0;
	uint8 card_num[8] = {0};
	int tran_money = 0;

	for(i=0; i<seek_count; i++){
		if(g_card.card_status == CARD_EXIST)
			break;
		setTimer(1,0);
	}
	if(i >= seek_count){
		printf("##libcard## write card fail, due to card no exist!\n");
		return 1;
	}

	memcpy(card_num,g_card.card->cardNUM,8);
	for(i=0; i<8; i++){
		if(card_num[i] != g_card.card->cardNUM[i]){
			printf("##libcard## write card fail,due to card number difference\n");
			return 1;
		}
	}

	re_state = check_card_valid();
	if(re_state == 0x59)
	{
		printf("##libcard## check card valid success!\n");
		re_state =  before_deal(g_card.card->pass,sizeof(g_card.card->pass));
		if(re_state == 0x59){
#ifdef USER_CARD
			tran_money =(int)(money*100);
			re_state = end_unlock_card(tran_money);
			if(re_state == 0x59)
				return 0;
			else if(re_state == 0x43){
				re_state = before_deal(g_card.card->pass,sizeof(g_card.card->pass));
				if(re_state == 0x59){
					if(g_card.grey_lock_state == 0x31){
						re_state = end_unlock_card(tran_money);
					}
					if(g_card.grey_lock_state == 0x30){
						re_state = sprang_open_card();
					}
					if(g_card.grey_lock_state == 0x32){
						for(i=0; i<3; i++){
							re_state = supplement_tran();
							if(re_state == 0x59)
							{
								re_state = sprang_open_card();
								break;
							}
							setTimer(0,250);
						}
						if(i >= 3)
							return 1;
					}
				}
				else
					return 1;
			}
			else
				return 1;
#endif
		}
		else
			return 1;
	}
	else
		return 1;

	return 0;
}

int protocol_exit_seek_card_status(void)
{
	g_card.read_card_flag = false;
	return 0;
}
